import re
import uuid
import datetime
import json
from bson import ObjectId
from flask import current_app, request, jsonify as flask_jsonify

def generate_id(prefix=''):
    """生成唯一ID"""
    unique_id = str(uuid.uuid4()).replace('-', '')[:10].upper()
    year = datetime.datetime.now().strftime('%Y')
    return f"{prefix}{year}{unique_id}"

def paginate(cursor, page=1, per_page=20):
    """将MongoDB游标分页"""
    page = int(page)
    per_page = int(per_page)
    
    # 确保页码至少为1
    if page < 1:
        page = 1
    
    # 计算跳过的文档数量
    skip = (page - 1) * per_page
    
    # 获取总文档数 - 使用兼容的方法，不依赖内部属性
    try:
        # 尝试直接使用count_documents()获取总数
        # 首先备份当前游标位置
        cursor_copy = cursor.clone()
        total = cursor_copy.count()
    except (AttributeError, TypeError):
        try:
            # 如果count()失败，尝试使用collection.count_documents()
            # 但我们需要提取查询条件
            collection = cursor.collection
            # 尝试获取查询条件
            try:
                # 对于新版本PyMongo
                filter_dict = cursor._Cursor__spec if hasattr(cursor, '_Cursor__spec') else {}
                if not filter_dict and hasattr(cursor, '_Cursor__filter'):
                    filter_dict = cursor._Cursor__filter
                # 如果仍然没有获取到过滤条件，就使用空字典
                if not filter_dict:
                    filter_dict = {}
                total = collection.count_documents(filter_dict)
            except Exception:
                # 如果所有尝试都失败，回退到获取整个集合的计数
                total = collection.count_documents({})
        except Exception:
            # 最后的回退：读取所有文档并计数
            total = sum(1 for _ in cursor.clone())
    
    # 获取当前页的文档
    items = list(cursor.skip(skip).limit(per_page))
    
    return {
        'items': items,
        'total': total,
        'page': page,
        'per_page': per_page,
        'pages': (total + per_page - 1) // per_page
    }

def parse_query_params():
    """解析查询参数"""
    params = {}
    for key, value in request.args.items():
        if key in ['page', 'limit', 'per_page', 'sort', 'order']:
            continue
        params[key] = value
    return params

def is_valid_object_id(id_string):
    """检查字符串是否为有效的ObjectId"""
    return ObjectId.is_valid(id_string)

def format_datetime(dt):
    """格式化日期时间为ISO 8601格式"""
    if isinstance(dt, (datetime.datetime, datetime.date)):
        return dt.isoformat()
    return dt

def format_id(obj_id):
    """将ObjectId转换为字符串"""
    if isinstance(obj_id, ObjectId):
        return str(obj_id)
    return obj_id

def normalize_data(data):
    """标准化数据，处理ObjectId和datetime"""
    if isinstance(data, dict):
        result = {}
        for key, value in data.items():
            if key == '_id':
                result['id'] = format_id(value)
            else:
                result[key] = normalize_data(value)
        return result
    elif isinstance(data, list):
        return [normalize_data(item) for item in data]
    elif isinstance(data, ObjectId):
        return format_id(data)
    elif isinstance(data, datetime.datetime):
        return format_datetime(data)
    elif isinstance(data, datetime.date):
        return format_datetime(data)
    else:
        return data

# 自定义jsonify函数，处理日期对象
def jsonify(*args, **kwargs):
    """增强的jsonify函数，可以处理日期和ObjectId"""
    if args and kwargs:
        raise TypeError('jsonify() behavior undefined when passed both args and kwargs')
    elif len(args) == 1:
        data = args[0]
    else:
        data = args or kwargs
    
    # 使用normalize_data处理数据
    normalized_data = normalize_data(data)
    
    # 使用Flask的jsonify处理格式化后的数据
    return flask_jsonify(normalized_data)

def allowed_file(filename):
    """检查文件是否为允许的类型"""
    # 只允许图片和文本文件
    allowed_image_extensions = ['jpg', 'jpeg', 'png', 'gif', 'bmp', 'webp', 'svg']
    allowed_text_extensions = ['txt', 'md', 'rtf', 'doc', 'docx', 'pdf']
    
    allowed_extensions = allowed_image_extensions + allowed_text_extensions
    
    return '.' in filename and filename.rsplit('.', 1)[1].lower() in allowed_extensions 